cocos2d

您所在的位置:网站首页 pop stars游戏 cocos2d

cocos2d

2024-07-12 16:47| 来源: 网络整理| 查看: 265

前言

说起PopStar这个游戏,或许很多人都不知道是啥,但是如果说起消灭星星的话,可能就会有很多人恍然大悟,原来是它。那么,这个消灭星星长得什么样子呢?我们用一张图来看看: 在这里插入图片描述emmm,是的,具体来说,长得就是这样,我们通过点击图片上某一个颜色的星星块,如果,这个颜色块周围存在和他相同的颜色块时,它就会消除掉所有相同的颜色块。直到屏幕上没有颜色块或者不能找到相邻的同色颜色块块时,游戏就结束。 以上呢就是游戏的一个玩法,而我们设计游戏的人,首先要了解的,也是这个游戏的玩法,并且提取有用信息,作为我们的头脑风暴的结果。比如以下几个点: 1.点击事件 2.消除相同颜色块 3.如果有消除,颜色块从上到下填充 4.如果某一列为空,颜色块从右往左填充

以上五点,应该就是整个游戏的核心功能。因此,我们接下来就逐一来探讨以下逻辑的实现:

1.如何响应点击事件

在cocos2d-x中,对鼠标的响应事件封装得很好,在本次的游戏中,我们只需要响应其单点响应即可,具体的一个写法可以为:

#创建一个鼠标监听对象 auto touchListener = EventListenerTouchOneByOne::create(); #为该对象指定相应事件 touchListener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this); #注册鼠标监听对象 Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(touchListener, this);

以上三个步骤,实际上应该是所有响应事件的日常操作了吧,当然也只是应该,毕竟我目前遇到的套路大致都如此,如果你不是用cocos来进行游戏开发的话,只需要把这部分调整成你所用的语言或者框架的响应事件逻辑即可。 以上,我们是实现了如何响应鼠标事件,但怎么响应呢?实际上就是上面代码中的第二部分:

#HelloWorld::onTouchBegan 此处为响应逻辑,也是主要的游戏逻辑入口 CC_CALLBACK_2(HelloWorld::onTouchBegan, this);

实际上,它在游戏中的逻辑是这样的:

bool HelloWorld::onTouchBegan(cocos2d::Touch *t, cocos2d::Event *e) { #获取当前颜色块 Vec2 point1 = t->getLocation(); Size visibleSize = Director::getInstance()->getVisibleSize(); PopSprite *cur = getPopSpriteByPoint(visibleSize, point1); if (cur != NULL) { index = 0; memset(visit, 0, sizeof(visit)); #收集相同颜色块 checkPopUDLR(cur); #删除相同颜色块 if (index>1) { for (int i = 0; i < index; i++) { sameStart[i]->setNumber(-1); } index = 0; } #更新上下 updateUD(); #更新左右 updateLR(); } return true; }

注意以上的几个注释:是不是就和我们剩下的几个步骤很是接近?实际上,这个游戏的核心都已经封装在这一小小的逻辑里面,那事不宜迟,我们来揭露以下的几个问题:

怎么收集到相同的颜色块?

这个问题其实很简单,获取相同的颜色块就如同走迷宫,如何获取全部可走的迷宫呢?这里用到的是深搜的思想:何为深搜,就是从当前的颜色块出发,按照上下左右(这里的顺序可以调整)去访问附近的颜色块,如果附近的颜色块颜色相同,重复搜索的步骤,否则,跳过。当等到不能在往下搜索的时候,就代表了全部的相同且相邻的颜色块被找齐了,此时,我们只需要用一个数组存储这些相同的颜色块,等到搜索结束后,删除即可:搜索部分如下:

/** 这部分是实现准备好的变量,所以此处注释了 #x的两个方向 int xx[4] = { 1,0,0,-1 }; #y的两个方向,联合就是针对x和y的上下左右四个方向 int yy[4] = { 0,1,-1,0 }; #是否被访问过,防止重复访问 int visit[10][10] = { 0 }; #保存相同颜色块的数组 PopSprite* sameStart[10*10];**/ void HelloWorld::checkPopUDLR(PopSprite* cur) { #获取当前颜色块的坐标 int x = cur->getX(); int y = cur->getY(); #设置该坐标的访问标识为1,代表访问过 visit[x][y] = 1; #添加当前颜色块 sameStart[index++] = cur; #循环,实现四个方向的轮询 for (int i = 0; i < 4; i++) { #获取第一个方向:根据xx和yy的顺序调整 int x1 = x + xx[i]; int y1 = y + yy[i]; #判断是否出界 if (x1 >= 0 && x1 < 10 && y1 >= 0 && y1 < 10) { #如果符合相同颜色,并且没有被访问过 if (popStarSprite[x1][y1]->getNumber() == cur->getNumber() && visit[x1][y1] == 0) { #从当前颜色块出发,继续轮询,知道所有轮询结束 checkPopUDLR(popStarSprite[x1][y1]); } } } }

通过上面的方法,我们就可以实现手机相同颜色块,接下来就是,消灭这些颜色块。具体如下:

#注意:此处的index代表相同颜色块的个数,如果index为1时 #代表只有一个颜色块,此时不做消灭操作 if (index>1) { #遍历所有颜色块,删除 #删除是指将其内部的值设置为初值,此处为-1 for (int i = 0; i < index; i++) { sameStart[i]->setNumber(-1); } #清空数组 index = 0; }

以上是消灭操作,消灭完之后,需要把空的地方天上,需要满足两个步骤:

上下填充,以及左右填充: 先看上下填充

上下填充的方式,其实是把每一列的星星抽出来,值为-1的值挪到前面,剩下的自然按顺序往下降,具体做法是:按从下网上的顺序,把值不为初值的数全部按顺序抽取排列,再把剩余的空位补-1.最后把这一列数按顺序回归该列:如下:

void HelloWorld::updateUD() { #轮询10列 for (int x = 0; x < 10; x++) { dataIndex = 0; #抽取每一列的各个数 for (int y = 0; y getNumber() != -1) { #将其放入新的数组 data[dataIndex++] = popStarSprite[x][y]->getNumber(); } } #剩下的位数,填充为-1 for(;dataIndexsetNumber(data[dataIndex++]); } } } 再看左右填充

左右填充的做法是:从左往右,查询某列为空,如果是,将其挪至最后一列,注意,如果已经挪了一次,则我们所查询的次数就响应减少即可:具体如

void HelloWorld::updateLR() { #从左往右遍历。此处的count初始为0,代表每有被挪动的列数 for (int x = 0; x < 9-count; x++) { #查询是否某列全部为空 bool isHasToLeft = true; for (int y = 0; y < 10; y++) { if (popStarSprite[x][y]->getNumber() != -1) { isHasToLeft = false; break; } } #如果为空,则 isHasToLeft值为true if (isHasToLeft) { # isHasToLeft值为true,代表需要挪动该列,count+1, count++; #往右挪动整列 for (int j=x; j< 9;j++) { for (int k = 0; k < 10; k++) { popStarSprite[j][k]->setNumber(popStarSprite[j + 1][k]->getNumber()); popStarSprite[j+1][k]->setNumber(-1); } } x--; } } }

至此:关于这款游戏的核心点已经讲解完毕:附上一个DEMO版本,仅供参考: 链接:https://pan.baidu.com/s/1U6v3TXS7A60FGVM6CbokPw 提取码:wobh



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3